import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

public class GamePanel extends JPanel {
    private static final int SIZE = 4;
    private  int[][] grid = new int[SIZE][SIZE];
    private final Random random = new Random();
    private boolean win=false, lose=false;
    GamePanel() {
        setFocusable(true);
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                boolean refreshFlag = false;
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_LEFT->{
                        moveLeft();
                        refreshFlag = true;
                    }
                    case KeyEvent.VK_RIGHT->{
                        moveRight();
                        refreshFlag = true;
                    }
                    case KeyEvent.VK_UP -> {
                        moveUp();
                        refreshFlag = true;
                    }
                    case KeyEvent.VK_DOWN->{
                        moveDown();
                        refreshFlag = true;
                    }
                }
                if(refreshFlag){
                    refresh();
                }
            }
        });
        setGridValue();
        setGridValue();
    }

    private void drawGrid(Graphics g, int value, int x, int y) {
        int p = (int) ((int) Math.log(value) / Math.log(2));
        g.setColor(value == 0 ? Color.LIGHT_GRAY : new Color(255 - p * 20, 240, 200));
        g.fillRect(x, y, 100, 100);
        g.setColor(Color.BLACK);
        g.drawRect(x, y, 100, 100);
        //g.getFont();
        g.drawString(String.valueOf(value), x+50, y+50);
    }
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(0, 0, getWidth(), getHeight());
        for(int i = 0; i < SIZE; i++) {
            for(int j = 0; j < SIZE; j++) {
                drawGrid(g, grid[i][j],j*100, i*100);
            }
        }
    }
    private void setGridValue() {
        int cnt = 0;
        for(int i=0; i<SIZE; i++) {
            for(int j=0; j<SIZE; j++) {
                if(grid[i][j] != 0) {
                    cnt++;
                }
            }
        }
        if(cnt == SIZE * SIZE) {
            return;
        }
        int x, y;
        do {
            x = random.nextInt(SIZE);
            y = random.nextInt(SIZE);
        } while (grid[x][y] != 0);
        grid[x][y] = random.nextInt(10) < 5 ? 2 : 4;
    }
    //向左移动
    private void moveLeft(){
        for(int i = 0; i < SIZE; i++) {
            int l=0,r=0;
            while (true){
                r++;
                if(r>=SIZE){
                    break;
                }else {
                    if(grid[i][l]==grid[i][r]){
                        grid[i][l]*=2;
                        grid[i][r]=0;
                        l++;
                    }else {
                        while (l!=r){
                            if(grid[i][l]==0){
                                grid[i][l]=grid[i][r];
                                grid[i][r]=0;
                            }else {
                                l++;
                            }
                        }
                    }
                }
            }
        }
    }
    //
    private void rotateRight(){
        int [][] newgrid = new int[SIZE][SIZE];
        for(int i = 0; i < SIZE; i++) {
            for(int j = 0; j < SIZE; j++) {
                newgrid[j][SIZE-i-1] = grid[i][j];
            }
        }
        grid=newgrid;
    }
    private void moveRight(){
        rotateRight();
        rotateRight();
        moveLeft();
        rotateRight();
        rotateRight();
    }
    private void moveUp(){
        rotateRight();
        rotateRight();
        rotateRight();
        moveLeft();
        rotateRight();
    }
    private void moveDown(){
        rotateRight();
        moveLeft();
        rotateRight();
        rotateRight();
        rotateRight();
    }

    void refresh(){
        repaint();
        setGridValue();
        checkGameState();
    }
    private void checkGameState(){
        int cnt = 0;
        for(int i=0; i<SIZE; i++) {
            for (int j=0; j<SIZE; j++) {
                if(grid[i][j]==2048){
                    win=true;
                    break;
                }else {
                    if(grid[i][j]!=0){
                        cnt++;
                    }
                }
            }
            if(win)
                break;
        }
        if(!win){
            if(cnt<SIZE*SIZE){
                return;
            }
            for(int i=0;i<SIZE;i++){
                for(int j=0;j<SIZE;j++){
                    if(i<SIZE-1&&grid[i][j] == grid[i+1][j])
                        return;
                    if (j<SIZE-1&&grid[i][j] == grid[i][j+1])
                        return;
                }
            }
            lose = true;
        }
    }
}
